package com.platform.metamodel;

import cn.hutool.core.convert.Convert;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
import org.apache.metamodel.data.DataSet;
import org.apache.metamodel.data.Row;
import org.apache.metamodel.query.SelectItem;

import java.lang.reflect.Field;
import java.sql.Clob;
import java.util.*;

/**
 * @author liujizheng
 * @version 1.0
 * @ClassName DataSetKit
 * @Description data set 小工具
 * @date 2021/9/26 11:49
 */
public final class DataSetKit {

    public static <T> T toBean(DataSet dataSet, Class<T> clazz) {
        return convert(toMap(dataSet), clazz);
    }

    public static <T> List<T> toBeanList(DataSet dataSet, Class<T> clazz) {
        List<T> result = new ArrayList<>();
        List<SelectItem> selects = dataSet.getSelectItems();
        dataSet.forEach(row -> {
            Map<String, Object> map = new HashMap<>(16);
            selects.forEach(item -> map.put(item.getColumn().getName(), row.getValue(item)));
            result.add(convert(map, clazz));
        });
        return result;
    }

    /**
     * 将dataset 转换成list map
     *
     * @param dataSet 数据集
     * @return 返回结果
     */
    @Deprecated
    public static List<Map<String, Object>> toListmap(DataSet dataSet) {
        return toMapList(dataSet);
    }

    /**
     * 将dataset 转换成list map
     *
     * @param dataSet 数据集
     * @return 返回结果
     */
    public static List<Map<String, Object>> toMapList(DataSet dataSet) {
        List<Map<String, Object>> result = new ArrayList<>();
        List<SelectItem> selects = dataSet.getSelectItems();
        dataSet.forEach(row -> {
            Map<String, Object> map = new HashMap<>(16);
            selects.forEach(item -> map.put(item.getColumn().getName(), row.getValue(item)));
            result.add(map);
        });
        return result;
    }

    /**
     * 将dataset 转换成list map(key为小写字母)
     *
     * @param dataSet 数据集
     * @return 返回结果
     */
    public static List<Map<String, Object>> toMapListLowerCase(DataSet dataSet) {
        List<Map<String, Object>> result = new ArrayList<>();
        List<SelectItem> selects = dataSet.getSelectItems();
        dataSet.forEach(row -> {
            Map<String, Object> map = new HashMap<>(16);
            selects.forEach(item -> {
                if (row.getValue(item) instanceof Clob){
                    map.put(item.getColumn().getName().toLowerCase(), row.getValue(item).toString());
                } else {
                    map.put(item.getColumn().getName().toLowerCase(), row.getValue(item));
                }
            });
            result.add(map);
        });
        return result;
    }

    /**
     * 将dataset 转换成list map(key为小写字母)
     *
     * @param dataSet 数据集
     * @return 返回结果
     */
    public static List<Map<String, Object>> toMapListLogical(DataSet dataSet,Map<String, String> logicalFieldMap) {
        List<Map<String, Object>> result = new ArrayList<>();
        List<SelectItem> selects = dataSet.getSelectItems();
        dataSet.forEach(row -> {
            Map<String, Object> map = new HashMap<>(16);
            selects.forEach(item -> {
                if (row.getValue(item) instanceof Clob){
                    map.put(logicalFieldMap.get(item.getColumn().getName().toLowerCase()), row.getValue(item).toString());
                } else {
                    map.put(logicalFieldMap.get(item.getColumn().getName().toLowerCase()), row.getValue(item));
                }
            });
            result.add(map);
        });
        return result;
    }


    public static Map<String, Object> toMap(DataSet dataSet) {
        if (!dataSet.next()) {
            return new HashMap<>(1);
        }
        Row row = dataSet.getRow();
        List<SelectItem> selects = row.getSelectItems();
        Map<String, Object> map = new HashMap<>(16);
        selects.forEach(item -> map.put(item.getColumn().getName(), row.getValue(item)));
        return map;
    }

    /**
     * 驼峰命名转下划线
     */
    private static Converter<String, String> converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.LOWER_UNDERSCORE);

    public static <T> T convert(Map<String, Object> map, Class<T> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        try {
            T o = clazz.newInstance();
            for (Field field : fields) {
                field.setAccessible(true);
                // 驼峰式命名
                String name = field.getName();
                Class<?> type = field.getType();
                Object value = map.get(converter.convert(name));
                if (Objects.isNull(value)) {
                    field.set(o, null);
                }
                field.set(o, Convert.convertWithCheck(type, value, null, false));
            }
            return o;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
